//
//  BinaryNode.swift
//  DataStructures
//
//  Created by  iBrother 李彦兵 on 2018/6/18.
//  Copyright © 2018 CEC-CESEC. All rights reserved.
//

import Foundation


public class BinaryNode<Element> {
    public var value: Element
    public var leftChild: BinaryNode?
    public var rightChild: BinaryNode?
    
    public init(value: Element) {
        self.value = value
    }
    
    public func travversePreOrder(visit: (Element) -> Void) {
        visit(value)
        leftChild?.travversePreOrder(visit: visit)
        rightChild?.travversePreOrder(visit: visit)
    }
    
    public func traversePostOrder(visit: (Element) -> Void) {
        leftChild?.traversePostOrder(visit: visit)
        rightChild?.traversePostOrder(visit: visit)
        visit(value)
    }
}


extension BinaryNode {
    public func traverseInOrder(visit: (Element) -> Void) {
        leftChild?.traverseInOrder(visit: visit)
        visit(value)
        rightChild?.traverseInOrder(visit: visit)
    }
}


extension BinaryNode: CustomStringConvertible {
    public var description: String {
        return diagram(for: self)
    }
    
    private func diagram(for node: BinaryNode?,
                             _ top: String = "",
                             _ root: String = "",
                             _ bottom: String = "") -> String {
        guard let node = node else {
            return root + "nil\n"
        }
        
        if node.leftChild == nil && node.rightChild == nil {
            return root + "\(node.value)\n"
        }
        
        return diagram(for: node, top + " ", top + "|- ", top + "| ")
    }
}
